package com.youlu.campus.admin.vote.service;

import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.admin.vote.dto.UserVoteSaveDTO;
import com.youlu.campus.admin.vote.dto.UserVoteSearchDTO;
import com.youlu.campus.admin.vote.vo.UserVoteResultVo;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.UserInfoExtend;
import com.youlu.campus.entity.vote.UserVotePointEntity;
import com.youlu.campus.service.course.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : [dengbo]
 * @className : UserVoteAdminService
 * @description : [用户投票后台服务]
 * @createTime : [2022/7/7 14:31]
 */
@Service
@Slf4j
public class UserVoteAdminService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MapperFacade mapperFacade;

    public Page<UserVoteResultVo> search(UserVoteSearchDTO dto) {
        QueryWrapper query = new QueryWrapper();
        query.where("activityId", dto.getActivityId());
        if (StringUtils.isNotBlank(dto.getUserId())) {
            query.where("userId", dto.getUserId());
        }
        if (StringUtils.isNotBlank(dto.getNickName())) {
            query.leftLike("nickName", dto.getNickName());
        }
        if (StringUtils.isNotBlank(dto.getMobile()) || StringUtils.isNotBlank(dto.getUserName()) || StringUtils.isNotBlank(dto.getNickName())) {
            QueryWrapper query2 = new QueryWrapper();
            if (StringUtils.isNotBlank(dto.getMobile())) {
                query2.where("mobile", dto.getMobile());
            }
            if (StringUtils.isNotBlank(dto.getUserName())) {
                query2.like("name", dto.getUserName());
            }
            List<UserInfoExtend> data = mongoTemplate.find(query2, UserInfoExtend.class);
            Map<String, UserInfoExtend> map = data.stream().collect(Collectors.toMap(UserInfoExtend::getUserId, Function.identity(), (o1, o2) -> o2));
            Set<String> userIdList = data.stream().map(UserInfoExtend::getUserId).collect(Collectors.toSet());
            query.addCriteria(Criteria.where("userId").in(userIdList));
            long count = mongoTemplate.count(query, UserVotePointEntity.class);
            query.with(Sort.by(Sort.Order.desc("id")));
            PageRequest pageRequest = PageRequest.of(dto.getPage() - 1, dto.getPageSize());
            query.with(pageRequest);
            List<UserVotePointEntity> list = mongoTemplate.find(query, UserVotePointEntity.class);
            return PageableExecutionUtils.getPage(entityToVo(list, map), pageRequest, () -> count);
        }
        long count = mongoTemplate.count(query, UserVotePointEntity.class);
        query.with(Sort.by(Sort.Order.desc("id")));
        PageRequest pageRequest = PageRequest.of(dto.getPage() - 1, dto.getPageSize());
        query.with(pageRequest);
        List<UserVotePointEntity> list = mongoTemplate.find(query, UserVotePointEntity.class);
        Set<String> uids = list.stream().map(UserVotePointEntity::getUserId).collect(Collectors.toSet());
        Query query2 = new Query();
        query2.addCriteria(Criteria.where("userId").in(uids));
        List<UserInfoExtend> data = mongoTemplate.find(query2, UserInfoExtend.class);
        Map<String, UserInfoExtend> map = data.stream().collect(Collectors.toMap(UserInfoExtend::getUserId, Function.identity(), (o1, o2) -> o2));
        return PageableExecutionUtils.getPage(entityToVo(list, map), pageRequest, () -> count);
    }

    public List<UserVoteResultVo> entityToVo(List<UserVotePointEntity> list, Map<String, UserInfoExtend> map) {
        return list.stream().map(item -> {
            UserVoteResultVo vo = mapperFacade.map(item, UserVoteResultVo.class);
            UserInfoExtend extend = map.get(item.getUserId());
            if (extend != null) {
                vo.setMobile(extend.getMobile());
                vo.setUserName(extend.getName());
                vo.setUniversityId(extend.getUniversityId());
                vo.setUniversityName(extend.getUniversityName());
            }
            return vo;
        }).collect(Collectors.toList());
    }

    public boolean save(UserVoteSaveDTO saveDTO) {
        Query query = new Query(Criteria.where("id").is(saveDTO.getId()));
        UserVotePointEntity point = mongoTemplate.findOne(query, UserVotePointEntity.class);
        if (point == null) {
            throw new BusinessException("用户信息不存在");
        }
        Update update = new Update();
        if (StringUtils.isNotBlank(saveDTO.getMobile())) {
            update.set("mobile", saveDTO.getMobile());
        }
        if (StringUtils.isNotBlank(saveDTO.getUserName())) {
            update.set("userName", saveDTO.getUserName());
        }
        if (StringUtils.isNotBlank(saveDTO.getUniversityId())) {
            update.set("universityId", saveDTO.getUniversityId());
        }
        if (StringUtils.isNotBlank(saveDTO.getUniversityName())) {
            update.set("universityName", saveDTO.getUniversityName());
        }
        if (saveDTO.getNum() != null) {
            if (point.getTotalNum() + saveDTO.getNum() < 0) {
                throw new BusinessException("可用票数不能小于0");
            }
            if (saveDTO.getNum() < 0) {
                query.addCriteria(Criteria.where("totalNum").gte(-saveDTO.getNum()));
            }
            update.inc("totalNum", saveDTO.getNum());
        }
        update.set("updatedTime", new Date());
        UpdateResult re = mongoTemplate.updateFirst(query, update, UserVotePointEntity.class);
        if (re.getModifiedCount() > 0) {
            if (StringUtils.isNotBlank(saveDTO.getMobile()) || StringUtils.isNotBlank(saveDTO.getUserName())) {
                // 更新扩展表
                Query exQuery = new Query();
                exQuery.addCriteria(Criteria.where("userId").is(point.getUserId()));
                Update exUpdate = new Update();
                if (StringUtils.isNotBlank(saveDTO.getMobile())) {
                    exUpdate.set("mobile", saveDTO.getMobile());
                }
                if (StringUtils.isNotBlank(saveDTO.getUserName())) {
                    exUpdate.set("name", saveDTO.getUserName());
                }
                if (StringUtils.isNotBlank(saveDTO.getUniversityName())) {
                    exUpdate.set("universityName", saveDTO.getUniversityName());
                }
                if (StringUtils.isNotBlank(saveDTO.getUniversityId())) {
                    exUpdate.set("universityId", saveDTO.getUniversityId());
                }
                mongoTemplate.updateFirst(exQuery, exUpdate, UserInfoExtend.class);
            }
        }
        return true;
    }
}
